import * as THREE from 'three';
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls';

export class ThreeModal {
  mouse: THREE.Vector2;
  raycaster: THREE.Raycaster;
  container: HTMLElement;
  camera: THREE.PerspectiveCamera;
  scene: THREE.Scene;
  defaultColors: string[];
  containerBox: any;
  containerCoord: {
    center: Pick<THREE.Vector3, 'x' | 'y' | 'z'>;
    scale: Pick<THREE.Vector3, 'x' | 'y' | 'z'>;
  } = {
    center: {
      x: 0,
      y: 0,
      z: 0,
    },
    scale: {
      x: 0,
      y: 0,
      z: 0,
    },
  };
  mesh: any[];
  renderer: THREE.WebGLRenderer = new THREE.WebGLRenderer({
    antialias: true,
    alpha: true,
  });
  downObj: any;
  INTERSECTED: any;

  boxList: any[];
  palletList: any[];

  constructor(container: HTMLElement, options: any) {
    this.container = container;
    this.boxList = options.boxList || [];
    this.palletList = options.palletList || [];

    this.init();
  }

  init() {
    this.mouse = new THREE.Vector2();
    this.raycaster = new THREE.Raycaster();
    this.camera = new THREE.PerspectiveCamera(
      55,
      this.container.clientWidth / this.container.clientHeight,
      1,
      2500
    );
    const len = this.containerCoord.scale.y;
    let position = 1000;
    // if(len < 13) {
    position = len < 15 ? 1000 : 1500;
    // }
    // console.log(len, position, this.containerCoord, this.containerBox)
    this.camera.position.set(position, position, position);
    this.scene = new THREE.Scene();
    const mesh = this.boxList.map((i, idx) => {
      const geometry = new THREE.BoxGeometry(i.scale.x, i.scale.y, i.scale.z);
      const material = new THREE.MeshBasicMaterial({
        color:
          this.defaultColors[Number(i.color)] ||
          this.defaultColors[idx % this.defaultColors.length],
      });
      material.transparent = true;
      material.opacity = 0.7;
      // material.morphTargets = true;
      const cube = new THREE.Mesh(geometry, material);
      cube.userData.id = i.id;
      cube.position.set(i.center.x, i.center.y, i.center.z);
      const detail = this.palletList.find((item) => item.uuid === i.id);
      cube.userData.detail = detail;
      return cube;
    });
    this.mesh = mesh;
    //
    if (mesh && mesh.length) {
      mesh.forEach((item) => {
        const box = new THREE.BoxHelper(item, 0x333333);
        this.scene.add(box);
      });
      this.scene.add(...mesh);
    }
    // var gridHelper = new THREE.GridHelper(3000, 40, 0x0000ff, 0x808080);
    // this.scene.add(gridHelper);
    const _containerBox = new THREE.Box3();

    _containerBox.setFromCenterAndSize(
      new THREE.Vector3(
        this.containerBox?.center?.x || 0,
        this.containerBox?.center?.y || 0,
        this.containerBox?.center?.z || 0
      ),
      new THREE.Vector3(
        this.containerBox?.scale?.x || 0,
        this.containerBox?.scale?.y || 0,
        this.containerBox?.scale?.z || 0
      )
    );

    const containerBoxHelper = new THREE.Box3Helper(_containerBox, 0x000000);
    this.scene.add(containerBoxHelper);

    this.renderer.setSize(
      this.container.clientWidth,
      this.container.clientHeight
    );
    this.container.appendChild(this.renderer.domElement);
    const controls = new OrbitControls(this.camera, this.renderer.domElement); // 创建控件对象
    controls.maxDistance = len < 15 ? 1200 : 1500;
    controls.target.set(
      this.containerBox?.center?.x || 0,
      this.containerBox?.center?.y || 0,
      this.containerBox?.center?.z || 0
    );
    controls.update();
    controls.addEventListener('change', this.render.bind(this));
    this.container.onmousedown = this.mousedown.bind(this); // 监听鼠标、键盘事件
    this.container.onmouseup = this.hightLight.bind(this); // 监听鼠标、键盘事件
  }

  mousedown(event) {
    this.downObj = {
      x: event.offsetX,
      y: event.offsetY,
    };
    // console.log(this.downObj);
  }

  hightLight(event) {
    const x = event.offsetX;
    const y = event.offsetY;
    if (Math.abs(x - this.downObj.x) > 5 || Math.abs(y - this.downObj.y) > 5) {
      return;
    }
    this.mouse.x = (x / this.container.clientWidth) * 2 - 1;
    this.mouse.y = -(y / this.container.clientHeight) * 2 + 1;
    this.raycaster.setFromCamera(this.mouse, this.camera);
    const intersects = this.raycaster.intersectObjects(this.mesh);
    if (intersects.length > 0) {
      // active(intersects[0].object);
      // console.log(intersects[0].object);
      // 拾取到的第一个模型不是当前高亮模型
      if (this.INTERSECTED !== intersects[0].object) {
        // 如果当前由高亮的模型,取消模型高亮
        if (this.INTERSECTED) {
          this.INTERSECTED.material.color.setHex(this.INTERSECTED.currentHex);
        }
        // 将拾取到的模型设为高亮
        this.INTERSECTED = intersects[0].object;
        // 保存高亮模型原本颜色
        this.INTERSECTED.currentHex = this.INTERSECTED.material.color.getHex();
        this.INTERSECTED.material.color.setHex(0xff0000);
      }
    } else {
    }
    this.renderer.render(this.scene, this.camera); // 执行渲染操作
  }

  render() {
    this.renderer.render(this.scene, this.camera);
  }
}
